/**
 *  test_slist.c - Test codes for slist_t and its functions.
 *                It runs on Windows or Linux.
 *
 *  Copyright (C) 2008  ZhangHu
 *  All rights reserved.
 *  E-MAIL: anmnmnly@gmail.com
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "test_slist.h"
#include "kernel/list.c"


static void test_add_node_single_list_head_0(void) {
    slist_t *_head = 0;
    slist_t *_pnew = 0;

    add_node_single_list_head(_head, _pnew);
}



static void test_add_node_single_list_head_1(void) {
    struct slist_t _head_0 = {0};
    slist_t *_head = &_head_0;

    slist_t *_pnew = 0;

    add_node_single_list_head(_head, _pnew);
    CU_ASSERT_PTR_NULL(_head->next);
}



static void test_add_node_single_list_head_2(void) {
    slist_t *_head = 0;

    struct slist_t _pnew_0 = {0};
    slist_t *_pnew = &_pnew_0;

    add_node_single_list_head(_head, _pnew);
}



static void test_add_node_single_list_head_3(void) {
    struct slist_t _head_0 = {0};
    slist_t *_head = &_head_0;

    struct slist_t _pnew_1 = {0};
    slist_t *_pnew = &_pnew_1;

    add_node_single_list_head(_head, _pnew);
    CU_ASSERT_PTR_EQUAL(_head->next, _pnew);
}



static void test_del_node_single_list_0(void) {
    slist_t *_head = 0;
    slist_t *_pdel = 0;

    slist_t *_result = del_node_single_list(_head, _pdel);
    CU_ASSERT_PTR_NULL(_result);
}



static void test_del_node_single_list_1(void) {
    struct slist_t _head_0 = {0};
    slist_t *_head = &_head_0;

    slist_t *_pdel = 0;

    slist_t *_result = del_node_single_list(_head, _pdel);
    CU_ASSERT_PTR_NULL(_result);
}



static void test_del_node_single_list_2(void) {
    slist_t *_head = 0;

    struct slist_t _pdel_0 = {0};
    slist_t *_pdel = &_pdel_0;

    slist_t *_result = del_node_single_list(_head, _pdel);
    CU_ASSERT_PTR_NULL(_result);
}



static void test_del_node_single_list_3(void) {
    struct slist_t _head_0 = {0};
    slist_t *_head  = &_head_0;

    struct slist_t _pdel_1 = {0};
    slist_t *_pdel = &_pdel_1;

    slist_t *_result  = del_node_single_list(_head, _pdel);
    CU_ASSERT_PTR_NULL(_result);
}



static void test_list_node_single_init_0(void) {
     slist_t *_node = 0;

     list_node_single_init(_node);
}


static void test_list_node_single_init_1(void) {
    struct slist_t _node_0 = {0};
    slist_t *_node = &_node_0;

    list_node_single_init(_node);
    CU_ASSERT_PTR_NULL(_node->next);
}



#define NODE_NUM 20

static slist_t head;
static slist_t *rear = NULL;

static void test_create_list(void) {
    int i;
    struct snode *p = NULL;
    slist_t *slist;

    for(i=0; i<NODE_NUM; i++) {
        if((p = (struct snode*)malloc(sizeof(struct snode))) == NULL) {
            printf("malloc is failed in create_list");
            break;
        } else {
            p->value = NODE_NUM - i - 1;
            add_node_single_list_head(&head, &p->link);
            if(i == 0) {
                rear = &p->link; // Pointer to the last node of linked list.
            }
        }
    }

    i = 0;
    slist = head.next;

    while(slist != NULL){
        p = mac_find_entry(slist, struct snode, link);
        CU_ASSERT_EQUAL(p->value, i++);
        slist = slist->next;
    }
}



static void test_destory_list(void) {
    struct snode *p = NULL;
    slist_t *slist = head.next;

    while(slist != NULL) {
        slist = del_node_single_list(&head, slist);
        p = mac_find_entry(slist, struct snode, link);
        free(p);
        slist = head.next;
    }
}



static void test_delete_first_node(void) {
    struct snode *p = NULL;
    slist_t *slist = head.next;

    slist = del_node_single_list(&head, slist);
    p = mac_find_entry(slist, struct snode, link);
    CU_ASSERT_EQUAL(p->value, 0);
    free(p);
}



static void test_delete_rear_node(void) {
    struct snode *p = NULL;
    int i = 1;
    slist_t *slist;

    rear = del_node_single_list(&head, rear);
    p = mac_find_entry(rear, struct snode, link);
    CU_ASSERT_EQUAL(p->value, NODE_NUM - 1);
    free(p);

    slist = head.next;
    while(slist != NULL){
        p = mac_find_entry(slist, struct snode, link);
        CU_ASSERT_EQUAL(p->value, i++);
        slist = slist->next;
    }

}



int test_slist_init(void) {
    printf("slist test ...\n\n");
    list_node_single_init(&head);

    return(0);
}



int test_slist_clean(void) {
    printf("slist test is over!\n\n");
    return(0);
}



CU_TestInfo test_slist_cases[] = {
    {"test_add_node_single_list_head_0", test_add_node_single_list_head_0},
    {"test_add_node_single_list_head_1", test_add_node_single_list_head_1},
    {"test_add_node_single_list_head_2", test_add_node_single_list_head_2},
    {"test_add_node_single_list_head_3", test_add_node_single_list_head_3},
    {"test_del_node_single_list_0", test_del_node_single_list_0},
    {"test_del_node_single_list_1", test_del_node_single_list_1},
    {"test_del_node_single_list_2", test_del_node_single_list_2},
    {"test_del_node_single_list_3", test_del_node_single_list_3},
    {"test_list_node_single_init_0", test_list_node_single_init_0},
    {"test_list_node_single_init_1", test_list_node_single_init_1},
    {"test_create_list", test_create_list},
    {"test_delete_first_node", test_delete_first_node},
    {"test_delete_rear_node", test_delete_rear_node},
    {"test_destory_list", test_destory_list},
    CU_TEST_INFO_NULL
};
